{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 梯度和优化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from math import pi\n",
    "import torch\n",
    "import torch.optim"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "求梯度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "函数值 = -1.0\n",
      "梯度值 = tensor([ 1.7321,  1.7321])\n",
      "梯度值(参考) = tensor([ 1.7321,  1.7321])\n"
     ]
    }
   ],
   "source": [
    "x = torch.tensor([pi / 3,  pi / 6], requires_grad=True)\n",
    "f = - ((x.cos() ** 2).sum()) ** 2\n",
    "print('函数值 = {}'.format(f))\n",
    "f.backward()\n",
    "print('梯度值 = {}'.format(x.grad))\n",
    "ref = 2 * (torch.cos(x) ** 2).sum() * torch.sin(2 * x)\n",
    "print('梯度值(参考) = {}'.format(ref))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "优化问题求解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step 0: x = [1.0471975803375244, 0.5235987901687622], f(x) = -1.0\n",
      "step 1: x = [0.8739925026893616, 0.35039371252059937], f(x) = -1.674528956413269\n",
      "step 2: x = [0.6192374229431152, 0.1835097223520279], f(x) = -2.6563119888305664\n",
      "step 3: x = [0.3111077845096588, 0.06654246151447296], f(x) = -3.617122173309326\n",
      "step 4: x = [0.08941137790679932, 0.016069628298282623], f(x) = -3.9671425819396973\n",
      "step 5: x = [0.01855570822954178, 0.0032690390944480896], f(x) = -3.99858021736145\n",
      "step 6: x = [0.0037171822041273117, 0.0006542906630784273], f(x) = -3.9999427795410156\n",
      "step 7: x = [0.0007434852886945009, 0.00013086205581203103], f(x) = -3.999997615814209\n",
      "step 8: x = [0.00014869746519252658, 2.6172441721428186e-05], f(x) = -4.0\n",
      "step 9: x = [2.973949449369684e-05, 5.234487616689876e-06], f(x) = -4.0\n",
      "step 10: x = [5.947898898739368e-06, 1.0468975233379751e-06], f(x) = -4.0\n"
     ]
    }
   ],
   "source": [
    "x = torch.tensor([pi / 3,  pi / 6], requires_grad=True)\n",
    "optimizer = torch.optim.SGD([x,], lr=0.1, momentum=0)\n",
    "for step in range(11):\n",
    "    if step:\n",
    "        optimizer.zero_grad()\n",
    "        f.backward()\n",
    "        optimizer.step()\n",
    "    f = - ((x.cos() ** 2).sum()) ** 2\n",
    "    print ('step {}: x = {}, f(x) = {}'.format(step, x.tolist(), f))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
